/**************************************************************************
**
** created by winter, 20181023
**
**************************************************************************/
#include "packagemanagerobj.h"

#include "component.h"
#include "componentmodel.h"
#include "errors.h"
#include "fileutils.h"
#include "messageboxhandler.h"
#include "packagemanagercore.h"
#include "progresscoordinator.h"
#include "performinstallationform.h"
#include "settings.h"
#include "utils.h"
#include "scriptengine.h"
#include "productkeycheck.h"

#include "sysinfo.h"

#include <QApplication>

#include <QtCore/QDir>
#include <QtCore/QPair>
#include <QtCore/QProcess>
#include <QtCore/QTimer>

#include <QAbstractItemView>
#include <QCheckBox>
#include <QComboBox>
#include <QDesktopServices>
#include <QFileDialog>
#include <QGridLayout>
#include <QHBoxLayout>
#include <QHeaderView>
#include <QLabel>
#include <QLineEdit>
#include <QListWidget>
#include <QListWidgetItem>
#include <QMessageBox>
#include <QProgressBar>
#include <QPushButton>
#include <QRadioButton>
#include <QStringListModel>
#include <QTextBrowser>
#include <QTreeView>
#include <QVBoxLayout>
#include <QShowEvent>
#include <QFileDialog>

#ifdef Q_OS_WIN
# include <qt_windows.h>
# include <QWinTaskbarButton>
# include <QWinTaskbarProgress>
#endif

using namespace KDUpdater;
using namespace QInstaller;




// -- PackageManagerGui::Private

class PackageManagerObj::Private
{
public:
    Private()
        : m_currentId(-1)
        //, m_modified(false)
        //, m_autoSwitchPage(true)
        //, m_useSettingsButton(true)
        //, m_showSettingsButton(false)
        //, m_silent(false)
        //, m_titleHeaderWidget(NULL)
    {
        /*m_wizardButtonTypes.insert(QWizard::BackButton, QLatin1String("QWizard::BackButton"));
        m_wizardButtonTypes.insert(QWizard::NextButton, QLatin1String("QWizard::NextButton"));
        m_wizardButtonTypes.insert(QWizard::CommitButton, QLatin1String("QWizard::CommitButton"));
        m_wizardButtonTypes.insert(QWizard::FinishButton, QLatin1String("QWizard::FinishButton"));
        m_wizardButtonTypes.insert(QWizard::CancelButton, QLatin1String("QWizard::CancelButton"));
        m_wizardButtonTypes.insert(QWizard::HelpButton, QLatin1String("QWizard::HelpButton"));
        m_wizardButtonTypes.insert(QWizard::CustomButton1, QLatin1String("QWizard::CustomButton1"));
        m_wizardButtonTypes.insert(QWizard::CustomButton2, QLatin1String("QWizard::CustomButton2"));
        m_wizardButtonTypes.insert(QWizard::CustomButton3, QLatin1String("QWizard::CustomButton3"));
        m_wizardButtonTypes.insert(QWizard::Stretch, QLatin1String("QWizard::Stretch"));*/
    }

    /*QString buttonType(int wizardButton)
    {
        return m_wizardButtonTypes.value(static_cast<QWizard::WizardButton>(wizardButton),
            QLatin1String("unknown button"));
    }*/

    int m_currentId;
    //bool m_modified;
    //bool m_autoSwitchPage;
    //bool m_useSettingsButton;
    //bool m_showSettingsButton;
    //bool m_silent;
    //QHash<int, QWizardPage*> m_defaultPages;
    //QHash<int, QString> m_defaultButtonText;
	QList<int> m_pageIds;
	QHash<int, PackageManagerPageObj*> m_pages;

    QJSValue m_controlScriptContext;
    //QHash<QWizard::WizardButton, QString> m_wizardButtonTypes;

    //TitleHeaderWidget* m_titleHeaderWidget;
};


// -- PackageManagerObj

/*!
    \class QInstaller::PackageManagerGui
    \inmodule QtInstallerFramework
    \brief The PackageManagerGui class provides the core functionality for non-interactive
        installations.
*/

/*!
    \fn void PackageManagerGui::interrupted()
    \sa {gui::interrupted}{gui.interrupted}
*/

/*!
    \fn void PackageManagerGui::languageChanged()
    \sa {gui::languageChanged}{gui.languageChanged}
*/

/*!
    \fn void PackageManagerGui::finishButtonClicked()
    \sa {gui::finishButtonClicked}{gui.finishButtonClicked}
*/

/*!
    \fn void PackageManagerGui::gotRestarted()
    \sa {gui::gotRestarted}{gui.gotRestarted}
*/

/*!
    \fn void PackageManagerGui::settingsButtonClicked()
    \sa {gui::settingsButtonClicked}{gui.settingsButtonClicked}
*/

/*!
    \fn void PackageManagerGui::setValidatorForCustomPageRequested(QInstaller::Component *component,
        const QString &name,
        const QString &callbackName)

    Sets a validator for the custom page specified by \a name and
    \a callbackName requested by \a component.
*/

/*!
    \fn void PackageManagerGui::packageManagerCore() const

    Returns the package manager core.
*/

/*!
    Constructs a package manager UI with package manager specified by \a core
    and \a parent as parent.
*/
PackageManagerObj::PackageManagerObj(PackageManagerCore *core, QObject *parent)
    : igui(Q_NULLPTR)
	, QObject(parent)
    , d(new Private)
    , m_core(core)
{
    /*if (m_core->isInstaller())
        setWindowTitle(tr("%1 Setup").arg(m_core->value(scTitle)));
    else
        setWindowTitle(tr("Maintain %1").arg(m_core->value(scTitle)));
    setWindowFlags(windowFlags() &~ Qt::WindowContextHelpButtonHint);*/

/*#ifndef Q_OS_OSX
    setWindowIcon(QIcon(m_core->settings().installerWindowIcon()));
#else
    setPixmap(QWizard::BackgroundPixmap, m_core->settings().background());
#endif
#ifdef Q_OS_LINUX
    setWizardStyle(QWizard::ModernStyle);
    setSizeGripEnabled(true);
#endif*/

    /*if (!m_core->settings().wizardStyle().isEmpty())
        setWizardStyle(getStyle(m_core->settings().wizardStyle()));*/

    // set custom stylesheet
    /*const QString styleSheetFile = m_core->settings().styleSheet();
    if (!styleSheetFile.isEmpty()) {
        QFile sheet(styleSheetFile);
        if (sheet.exists()) {
            if (sheet.open(QIODevice::ReadOnly))
                setStyleSheet(QString::fromLatin1(sheet.readAll()));
            else
                qWarning() << "The specified style sheet file can not be opened.";
        } else {
            qWarning() << "A style sheet file is specified, but it does not exist.";
        }
    }*/

    /*setOption(QWizard::NoBackButtonOnStartPage);
    setOption(QWizard::NoBackButtonOnLastPage);*/

    //connect(this, &QDialog::rejected, m_core, &PackageManagerCore::setCanceled);
	connect(this, &PackageManagerObj::objReject, m_core, &PackageManagerCore::setCanceled);
    connect(this, &PackageManagerObj::interrupted, m_core, &PackageManagerCore::interrupt);

    // both queued to show the finished page once everything is done
    connect(m_core, &PackageManagerCore::installationFinished,
            this, &PackageManagerObj::showFinishedPage,
        Qt::QueuedConnection);
    connect(m_core, &PackageManagerCore::uninstallationFinished,
            this, &PackageManagerObj::showFinishedPage,
        Qt::QueuedConnection);

    //connect(this, &QWizard::currentIdChanged, this, &PackageManagerGui::currentPageChanged);
    //connect(this, &QWizard::currentIdChanged, m_core, &PackageManagerCore::currentPageChanged);
    /*connect(button(QWizard::FinishButton), &QAbstractButton::clicked,
            this, &PackageManagerGui::finishButtonClicked);
    connect(button(QWizard::FinishButton), &QAbstractButton::clicked,
            m_core, &PackageManagerCore::finishButtonClicked);*/
	connect(this, &PackageManagerObj::finishButtonClicked,
		m_core, &PackageManagerCore::finishButtonClicked);

    // make sure the QUiLoader's retranslateUi is executed first, then the script
    connect(this, &PackageManagerObj::languageChanged,
            m_core, &PackageManagerCore::languageChanged, Qt::QueuedConnection);
    /*connect(this, &PackageManagerGui::languageChanged,
            this, &PackageManagerGui::onLanguageChanged, Qt::QueuedConnection);*/

    connect(m_core,
        &PackageManagerCore::wizardPageInsertionRequested,
        this, &PackageManagerObj::wizardPageInsertionRequested);
    connect(m_core, &PackageManagerCore::wizardPageRemovalRequested,
            this, &PackageManagerObj::wizardPageRemovalRequested);
    connect(m_core, &PackageManagerCore::wizardWidgetInsertionRequested,
        this, &PackageManagerObj::wizardWidgetInsertionRequested);
    connect(m_core, &PackageManagerCore::wizardWidgetRemovalRequested,
            this, &PackageManagerObj::wizardWidgetRemovalRequested);
    connect(m_core, &PackageManagerCore::wizardPageVisibilityChangeRequested,
            this, &PackageManagerObj::wizardPageVisibilityChangeRequested, Qt::QueuedConnection);

    connect(m_core, &PackageManagerCore::setValidatorForCustomPageRequested,
            this, &PackageManagerObj::setValidatorForCustomPageRequested);

    /*connect(m_core, &PackageManagerCore::setAutomatedPageSwitchEnabled,
            this, &PackageManagerObj::setAutomatedPageSwitchEnabled);*/

    //connect(this, &QWizard::customButtonClicked, this, &PackageManagerGui::customButtonClicked);

    /*for (int i = QWizard::BackButton; i < QWizard::CustomButton1; ++i)
        d->m_defaultButtonText.insert(i, buttonText(QWizard::WizardButton(i)));*/
	PackageManagerObj* p = this;
	QObject* p2 = this;
	igui* p3 = (igui*)(this);
	igui* p4 = (igui*)(p2);
    m_core->setGuiObject(this);
}

/*!
    Destructs a package manager UI.
*/
PackageManagerObj::~PackageManagerObj()
{
    m_core->setGuiObject(0);
    delete d;
}

//////
QString PackageManagerObj::objTitle()
{
	return m_core->value(scTitle);
}
QString PackageManagerObj::objWindowTitle()
{
	if (m_core->isInstaller())
		return tr("%1 Setup").arg(m_core->value(scTitle));
	else
		return tr("Maintain %1").arg(m_core->value(scTitle));
}
#ifndef Q_OS_OSX
QString PackageManagerObj::objWindowIcon()
{
	return m_core->settings().installerWindowIcon();
}
#else
QString PackageManagerObj::objBackground()
{
	return m_core->settings().background();
}
#endif
QWizard::WizardStyle PackageManagerObj::objWizardStyle()
{
	return getStyle(m_core->settings().wizardStyle());
}

QString PackageManagerObj::objStyleSheet()
{
	const QString styleSheetFile = m_core->settings().styleSheet();
	if (!styleSheetFile.isEmpty()) {
		QFile sheet(styleSheetFile);
		if (sheet.exists()) {
			if (sheet.open(QIODevice::ReadOnly))
				return QString::fromLatin1(sheet.readAll());
			else
				qWarning() << "The specified style sheet file can not be opened.";
		}
		else {
			qWarning() << "A style sheet file is specified, but it does not exist.";
		}
	}

	return QLatin1String();
}

int PackageManagerObj::objCurrentId()
{
	return d->m_currentId;
}

void PackageManagerObj::addPage(int id, PackageManagerPageObj* page)
{
	d->m_pageIds.append(id);
	d->m_pages[id] = page;
}

void PackageManagerObj::setPage(int index, int id, PackageManagerPageObj* page)
{
	d->m_pageIds.insert(index, id);
	d->m_pages[id] = page;
}

void PackageManagerObj::removePage(int id)
{
	d->m_pageIds.removeAll(id);
}

QList<int> PackageManagerObj::pageIds()
{
	return d->m_pageIds;
}

int PackageManagerObj::nextId()
{
	int id = objCurrentId();
	int index = d->m_pageIds.indexOf(id);
	if (index == -1) return -1;
	index++;
	if (index >= d->m_pageIds.count()) return -1;
	return d->m_pageIds[index];
}

PackageManagerPageObj* PackageManagerObj::page(int id)
{
	return d->m_pages[id];
}

QObject* PackageManagerObj::myPage(int id) 
{ 
	return page(id);
}

void PackageManagerObj::nextPage()
{
	currentPageChanged(this->nextId());
}

/*void PackageManagerObj::objSetCurrentId(PackageManagerCore::WizardPage newId)
{
	d->m_currentId = newId;
	executeControlScript(newId);
}*/

/*!
    Returns the style of the package manager UI depending on \a name:

    \list
        \li \c Classic - Classic UI style for Windows 7 and earlier.
        \li \c Modern - Modern UI style for Windows 8.
        \li \c Mac - UI style for OS X.
        \li \c Aero - Aero Peek for Windows 7.
    \endlist
*/
QWizard::WizardStyle PackageManagerObj::getStyle(const QString &name)
{
    if (name == QLatin1String("Classic"))
        return QWizard::ClassicStyle;

    if (name == QLatin1String("Modern"))
        return QWizard::ModernStyle;

    if (name == QLatin1String("Mac"))
        return QWizard::MacStyle;

    if (name == QLatin1String("Aero"))
        return QWizard::AeroStyle;

    // add by winter, 20180117
    if (name == QLatin1String("N"))
        return QWizard::NStyles;

    return QWizard::ModernStyle;
}

/*!
   Hides the GUI when \a silent is \c true.
*/
/*void PackageManagerObj::setSilent(bool silent)
{
  d->m_silent = silent;
  //setVisible(!silent);
}*/

/*!
    Returns the current silent state.
*/
/*bool PackageManagerObj::isSilent() const
{
  return d->m_silent;
}*/

/*!
    Updates the model of \a object (which must be a QComboBox or
    QAbstractItemView) such that it contains the given \a items.
*/
/*void PackageManagerGui::setTextItems(QObject *object, const QStringList &items)
{
    if (QComboBox *comboBox = qobject_cast<QComboBox*>(object)) {
        comboBox->setModel(new QStringListModel(items));
        return;
    }

    if (QAbstractItemView *view = qobject_cast<QAbstractItemView*>(object)) {
        view->setModel(new QStringListModel(items));
        return;
    }

    qDebug() << "Cannot set text items on object of type"
             << object->metaObject()->className() << ".";
}*/

/*!
    Enables automatic page switching when \a request is \c true.
*/
/*void PackageManagerObj::setAutomatedPageSwitchEnabled(bool request)
{
    d->m_autoSwitchPage = request;
}*/

/*!
    Returns the default text for the button specified by \a wizardButton.

    \sa {gui::defaultButtonText}{gui.defaultButtonText}
*/
/*QString PackageManagerGui::defaultButtonText(int wizardButton) const
{
    return d->m_defaultButtonText.value(wizardButton);
}*/

/*
    Check if we need to "transform" the finish button into a cancel button, caused by the misuse of
    cancel as the finish button on the FinishedPage. This is only a problem if we run as updater or
    package manager, as then there will be two button shown on the last page with the cancel button
    renamed to "Finish".
*/
/*static bool swapFinishButton(PackageManagerCore *core, int currentId, int button)
{
    if (button != QWizard::FinishButton)
        return false;

    if (currentId != PackageManagerCore::InstallationFinished)
        return false;

    if (core->isInstaller() || core->isUninstaller())
        return false;

    return true;
}*/

/*!
    Clicks the button specified by \a wb after the delay specified by \a delay.

    \sa {gui::clickButton}{gui.clickButton}
*/
/*void PackageManagerGui::clickButton(int wb, int delay)
{
    // We need to to swap here, cause scripts expect to call this function with FinishButton on the
    // finish page.
    if (swapFinishButton(m_core, currentId(), wb))
        wb = QWizard::CancelButton;

    if (QAbstractButton *b = button(static_cast<QWizard::WizardButton>(wb)))
        QTimer::singleShot(delay, b, &QAbstractButton::click);
    else
        qWarning() << "Button with type: " << d->buttonType(wb) << "not found!";
}*/

/*!
    Returns \c true if the button specified by \a wb is enabled. Returns \c false
    if a button of the specified type is not found.

    \sa {gui::isButtonEnabled}{gui.isButtonEnabled}
*/
/*bool PackageManagerGui::isButtonEnabled(int wb)
{
    // We need to to swap here, cause scripts expect to call this function with FinishButton on the
    // finish page.
    if (swapFinishButton(m_core, currentId(), wb))
            wb = QWizard::CancelButton;

    if (QAbstractButton *b = button(static_cast<QWizard::WizardButton>(wb)))
        return b->isEnabled();

    qWarning() << "Button with type: " << d->buttonType(wb) << "not found!";
    return false;
}*/

/*!
    Sets a validator for the custom page specified by \a name and
    \a callbackName requested by \a component.
*/
/*void PackageManagerGui::setValidatorForCustomPageRequested(Component *component,
    const QString &name, const QString &callbackName)
{
    component->setValidatorCallbackName(callbackName);

    const QString componentName = QLatin1String("Dynamic") + name;
    const QList<int> ids = pageIds();
    foreach (const int i, ids) {
        PackageManagerPage *const p = qobject_cast<PackageManagerPage*> (page(i));
        if (p && p->objectName() == componentName) {
            p->setValidatePageComponent(component);
            return;
        }
    }
}*/

/*!
    Loads the script specified by \a scriptPath to perform the installation non-interactively.
    Throws QInstaller::Error if the script is not readable or it cannot be
    parsed.
*/
void PackageManagerObj::loadControlScript(const QString &scriptPath)
{
    d->m_controlScriptContext = m_core->controlScriptEngine()->loadInContext(
        QLatin1String("Controller"), scriptPath);
    qDebug() << "Loaded control script" << scriptPath;
}

/*!
    Calls the control script method specified by \a methodName.
*/
void PackageManagerObj::callControlScriptMethod(const QString &methodName)
{
    if (d->m_controlScriptContext.isUndefined())
        return;
    try {
        const QJSValue returnValue = m_core->controlScriptEngine()->callScriptMethod(
            d->m_controlScriptContext, methodName);
        if (returnValue.isUndefined()) {
            qDebug() << "Control script callback" << methodName << "does not exist.";
            return;
        }
    } catch (const QInstaller::Error &e) {
        qCritical() << qPrintable(e.message());
    }
}

/*!
    Executes the control script on the page specified by \a pageId.
*/
void PackageManagerObj::executeControlScript(int pageId)
{
    if (PackageManagerPageObj *const p = qobject_cast<PackageManagerPageObj*> (page(pageId)))
        callControlScriptMethod(p->objectName() + QLatin1String("Callback"));
}

/*!
    Replaces the default button text with translated text when the application
    language changes.
*/
/*void PackageManagerGui::onLanguageChanged()
{
    d->m_defaultButtonText.clear();
    for (int i = QWizard::BackButton; i < QWizard::CustomButton1; ++i)
        d->m_defaultButtonText.insert(i, buttonText(QWizard::WizardButton(i)));
}*/

/*!
    \reimp
*/
/*bool PackageManagerGui::event(QEvent *event)
{
    switch(event->type()) {
    case QEvent::LanguageChange:
        emit languageChanged();
        break;
    default:
        break;
    }
    return QWizard::event(event);
}*/

/*!
    \reimp
*/
void PackageManagerObj::showEvent(QShowEvent *event)
{
    /*if (!event->spontaneous()) {
        foreach (int id, pageIds()) {
            const QString subTitle = page(id)->subTitle();
            if (subTitle.isEmpty()) {
                const QWizard::WizardStyle style = wizardStyle();
                if ((style == QWizard::ClassicStyle) || (style == QWizard::ModernStyle)) {
                    // otherwise the colors might screw up
                    page(id)->setSubTitle(QLatin1String(" "));
                }
            }
        }
        setMinimumSize(size());
        if (minimumWidth() < m_core->settings().wizardDefaultWidth())
            resize(m_core->settings().wizardDefaultWidth(), height());
        if (minimumHeight() < m_core->settings().wizardDefaultHeight())
            resize(width(), m_core->settings().wizardDefaultHeight());
    }
    QWizard::showEvent(event);*/
    QMetaObject::invokeMethod(this, "dependsOnLocalInstallerBinary", Qt::QueuedConnection);
}

/*!
    Requests the insertion of the page specified by \a widget at the position specified by \a page.
    If that position is already occupied by another page, the value is decremented until an empty
    slot is found.
*/
/*void PackageManagerGui::wizardPageInsertionRequested(QWidget *widget,
    QInstaller::PackageManagerCore::WizardPage page)
{
    // just in case it was already in there...
    wizardPageRemovalRequested(widget);

    int pageId = static_cast<int>(page) - 1;
    while (QWizard::page(pageId) != 0)
        --pageId;

    // add it
    setPage(pageId, new DynamicInstallerPage(widget, m_core));
}*/

/*!
    Requests the removal of the page specified by \a widget.
*/
/*void PackageManagerGui::wizardPageRemovalRequested(QWidget *widget)
{
    foreach (int pageId, pageIds()) {
        DynamicInstallerPage *const dynamicPage = qobject_cast<DynamicInstallerPage*>(page(pageId));
        if (dynamicPage == 0)
            continue;
        if (dynamicPage->widget() != widget)
            continue;
        removePage(pageId);
        d->m_defaultPages.remove(pageId);
        packageManagerCore()->controlScriptEngine()->removeFromGlobalObject(dynamicPage);
        packageManagerCore()->componentScriptEngine()->removeFromGlobalObject(dynamicPage);
    }
}*/

/*!
    Requests the insertion of \a widget on \a page.
*/
/*void PackageManagerGui::wizardWidgetInsertionRequested(QWidget *widget,
    QInstaller::PackageManagerCore::WizardPage page)
{
    Q_ASSERT(widget);
    if (QWizardPage *const p = QWizard::page(page)) {
        p->layout()->addWidget(widget);
        packageManagerCore()->controlScriptEngine()->addToGlobalObject(p);
        packageManagerCore()->componentScriptEngine()->addToGlobalObject(p);
    }
}*/

/*!
    Requests the removal of \a widget from installer pages.
*/
/*void PackageManagerGui::wizardWidgetRemovalRequested(QWidget *widget)
{
    Q_ASSERT(widget);
    widget->setParent(0);
    packageManagerCore()->controlScriptEngine()->removeFromGlobalObject(widget);
    packageManagerCore()->componentScriptEngine()->removeFromGlobalObject(widget);
}*/

/*!
    Requests changing the visibility of the page specified by \a p to
    \a visible.
*/
/*void PackageManagerGui::wizardPageVisibilityChangeRequested(bool visible, int p)
{
    if (visible && page(p) == 0) {
        setPage(p, d->m_defaultPages[p]);
    } else if (!visible && page(p) != 0) {
        d->m_defaultPages[p] = page(p);
        removePage(p);
    }
}*/

/*!
    Returns the page specified by \a id.

    \sa {gui::pageById}{gui.pageById}
*/
/*QWidget *PackageManagerGui::pageById(int id) const
{
    return page(id);
}*/

/*!
    Returns the page specified by the object name \a name from a UI file.

    \sa {gui::pageByObjectName}{gui.pageByObjectName}
*/
/*QWidget *PackageManagerGui::pageByObjectName(const QString &name) const
{
    const QList<int> ids = pageIds();
    foreach (const int i, ids) {
        PackageManagerPage *const p = qobject_cast<PackageManagerPage*> (page(i));
        if (p && p->objectName() == name)
            return p;
    }
    qWarning() << "No page found for object name" << name;
    return 0;
}*/

/*!
    \sa {gui::currentPageWidget}{gui.currentPageWidget}
*/
/*QWidget *PackageManagerGui::currentPageWidget() const
{
    return currentPage();
}*/

/*!
    For dynamic pages, returns the widget specified by \a name read from the UI
    file.

    \sa {gui::pageWidgetByObjectName}{gui.pageWidgetByObjectName}
*/
/*QWidget *PackageManagerGui::pageWidgetByObjectName(const QString &name) const
{
    QWidget *const widget = pageByObjectName(name);
    if (PackageManagerPage *const p = qobject_cast<PackageManagerPage*> (widget)) {
        // For dynamic pages, return the contained widget (as read from the UI file), not the
        // wrapper page
        if (DynamicInstallerPage *dp = qobject_cast<DynamicInstallerPage *>(p))
            return dp->widget();
        return p;
    }
    qWarning() << "No page found for object name" << name;
    return 0;
}*/

/*!
    \sa {gui::cancelButtonClicked}{gui.cancelButtonClicked}
*/
void PackageManagerObj::cancelButtonClicked()
{
    const int id = objCurrentId();
    if (id == PackageManagerCore::Introduction || id == PackageManagerCore::InstallationFinished) {
        m_core->setNeedsHardRestart(false);
        //QDialog::reject(); 
		emit objReject();
		return;
    }

    /*QString question;
    bool interrupt = false;
    PackageManagerPage *const page = qobject_cast<PackageManagerPage*> (currentPage());
    if (page && page->isInterruptible()
        && m_core->status() != PackageManagerCore::Canceled
        && m_core->status() != PackageManagerCore::Failure) {
            interrupt = true;
            question = tr("Do you want to cancel the installation process?");
            if (m_core->isUninstaller())
                question = tr("Do you want to cancel the uninstallation process?");
    } else {
        question = tr("Do you want to quit the installer application?");
        if (m_core->isUninstaller())
            question = tr("Do you want to quit the uninstaller application?");
        if (m_core->isMaintainer())
            question = tr("Do you want to quit the maintenance application?");
    }

    const QMessageBox::StandardButton button =
        MessageBoxHandler::question(MessageBoxHandler::currentBestSuitParent(),
        QLatin1String("cancelInstallation"), tr("%1 Question").arg(m_core->value(scTitle)), question,
        QMessageBox::Yes | QMessageBox::No);*/

	bool interrupt = false;
	QMessageBox::StandardButton button = QMessageBox::Yes;
	emit objCancelAsk(button, interrupt);

    if (button == QMessageBox::Yes) {
        if (interrupt)
            emit interrupted();
        else
            //QDialog::reject();
			emit objReject();
    }
}

/*!
   \sa {gui::rejectWithoutPrompt}{gui.rejectWithoutPrompt}
*/
void PackageManagerObj::rejectWithoutPrompt()
{
    //QDialog::reject();
	emit objReject();
}

/*!
    \reimp
*/
void PackageManagerObj::reject()
{
    cancelButtonClicked();
}

/*!
    \internal
*/
/*void PackageManagerGui::setModified(bool value)
{
    d->m_modified = value;
}*/

/*!
    \sa {gui::showFinishedPage}{gui.showFinishedPage}
*/
void PackageManagerObj::showFinishedPage()
{
    /*if (d->m_autoSwitchPage)
        next();
    else
        qobject_cast<QPushButton*>(button(QWizard::CancelButton))->setEnabled(false);*/

	currentPageChanged(PackageManagerCore::InstallationFinished);
}

/*void PackageManagerGui::useSettingsButton(bool use)
{
    d->m_useSettingsButton = use;
}*/

/*!
    Shows the \uicontrol Settings button if \a show is \c true.

    \sa {gui::showSettingsButton}{gui.showSettingsButton}
*/
/*void PackageManagerGui::showSettingsButton(bool show)
{
    if (!d->m_useSettingsButton) return;
    if (d->m_showSettingsButton == show)
        return;

    d->m_showSettingsButton = show;
    setOption(QWizard::HaveCustomButton1, show);
    setButtonText(QWizard::CustomButton1, tr("Settings"));

    updateButtonLayout();
}*/

/*!
    Forces an update of our own button layout. Needs to be called whenever a
    button option has been set.
*/
/*void PackageManagerGui::updateButtonLayout()
{
    QVector<QWizard::WizardButton> buttons(12, QWizard::NoButton);
    if (options() & QWizard::HaveHelpButton)
        buttons[(options() & QWizard::HelpButtonOnRight) ? 11 : 0] = QWizard::HelpButton;

    buttons[1] = QWizard::Stretch;
    if (options() & QWizard::HaveCustomButton1) {
        buttons[1] = QWizard::CustomButton1;
        buttons[2] = QWizard::Stretch;
    }

    if (options() & QWizard::HaveCustomButton2)
        buttons[3] = QWizard::CustomButton2;

    if (options() & QWizard::HaveCustomButton3)
        buttons[4] = QWizard::CustomButton3;

    if (!(options() & QWizard::NoCancelButton))
        buttons[(options() & QWizard::CancelButtonOnLeft) ? 5 : 10] = QWizard::CancelButton;

    buttons[6] = QWizard::BackButton;
    buttons[7] = QWizard::NextButton;
    buttons[8] = QWizard::CommitButton;
    buttons[9] = QWizard::FinishButton;

    setOption(QWizard::NoBackButtonOnLastPage, true);
    setOption(QWizard::NoBackButtonOnStartPage, true);

    setButtonLayout(buttons.toList());
}*/

/*!
    Enables the \uicontrol Settings button by setting \a enabled to \c true.

    \sa {gui::setSettingsButtonEnabled}{gui.setSettingsButtonEnabled}
*/
/*void PackageManagerGui::setSettingsButtonEnabled(bool enabled)
{
    if (QAbstractButton *btn = button(QWizard::CustomButton1))
        btn->setEnabled(enabled);
}*/

/*!
    Emits the settingsButtonClicked() signal when the custom button specified by \a which is
    clicked if \a which is the \uicontrol Settings button.
*/
/*void PackageManagerGui::customButtonClicked(int which)
{
    if (QWizard::WizardButton(which) == QWizard::CustomButton1 && d->m_showSettingsButton)
        emit settingsButtonClicked();
}*/

/*!
    Prevents installation from a network location by determining that a local
    installer binary must be used.
*/
void PackageManagerObj::dependsOnLocalInstallerBinary()
{
    if (m_core->settings().dependsOnLocalInstallerBinary() && !m_core->localInstallerBinaryUsed()) {
        MessageBoxHandler::critical(MessageBoxHandler::currentBestSuitParent(),
            QLatin1String("Installer_Needs_To_Be_Local_Error"), tr("Error"),
            tr("It is not possible to install from network location.\n"
               "Please copy the installer to a local drive"), QMessageBox::Ok);
        rejectWithoutPrompt();
    }
}

/*!
    Called when the current page changes to \a newId. Calls the leaving() method for the old page
    and the entering() method for the new one. Also, executes the control script associated with the
    new page by calling executeControlScript().

    Emits the left() and entered() signals.
*/
void PackageManagerObj::currentPageChanged(int newId)
{
	emit m_core->currentPageChanged(newId);

	PackageManagerPageObj *oldPage = qobject_cast<PackageManagerPageObj *>(page(d->m_currentId));
    if (oldPage) {
        oldPage->leaving();
        emit oldPage->left();
    }

    d->m_currentId = newId;

	PackageManagerPageObj *newPage = qobject_cast<PackageManagerPageObj *>(page(d->m_currentId));
    if (newPage) {
        newPage->entering();
        emit newPage->entered();
    }

    executeControlScript(newId);	
}

// show self define title bar, winter, 20180117
/*void PackageManagerGui::showHeadTitle(bool show, const QString& titleName)
{
    if(show && d->m_titleHeaderWidget == Q_NULLPTR)
        d->m_titleHeaderWidget = new  TitleHeaderWidget(this);

    if (d->m_titleHeaderWidget != Q_NULLPTR)
    {
        d->m_titleHeaderWidget->setVisible(show);
        d->m_titleHeaderWidget->setTitle(titleName);
    }
}

QWidget* PackageManagerGui::showProtocol(const QString& text, int x, int y, int width, int height)
{
    QWidget *ProtocolWidget;
    QHBoxLayout *ProtocolLayout;
    QCheckBox *ProtocolCheckBox;
    QLabel *ProtocolLabel;

    ProtocolWidget = new QWidget(this);
    ProtocolWidget->setObjectName(QStringLiteral("ProtocolWidget"));
    ProtocolWidget->setGeometry(QRect(x, y, width, height));
    ProtocolLayout = new QHBoxLayout(ProtocolWidget);
    ProtocolLayout->setObjectName(QStringLiteral("ProtocolLayout"));
    ProtocolLayout->setContentsMargins(0, 0, 0, 0);
    ProtocolCheckBox = new QCheckBox(ProtocolWidget);
    ProtocolCheckBox->setObjectName(QStringLiteral("ProtocolCheckBox"));

    ProtocolLayout->addWidget(ProtocolCheckBox);

    ProtocolLabel = new QLabel(ProtocolWidget);
    ProtocolLabel->setObjectName(QStringLiteral("ProtocolLabel"));
    ProtocolLabel->setText(text);
    QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
    sizePolicy.setHorizontalStretch(0);
    sizePolicy.setVerticalStretch(0);
    sizePolicy.setHeightForWidth(ProtocolLabel->sizePolicy().hasHeightForWidth());
    ProtocolLabel->setSizePolicy(sizePolicy);

    ProtocolLayout->addWidget(ProtocolLabel);

    return ProtocolWidget;
}

QWidget* PackageManagerGui::showTipLabel(const QString& text, int x, int y, int width, int height)
{
    QLabel *TipLabel = new QLabel(this);
    TipLabel->setObjectName(QStringLiteral("TipLabel"));
    TipLabel->setText(text);
    TipLabel->setGeometry(QRect(x, y, width, height));

    return TipLabel;
}

void PackageManagerGui::setDragHeight(int iHeight)
{
    d->m_titleHeaderWidget->setDragHeight(iHeight);
}

void PackageManagerGui::setButtonText2(int wizardButton, const QString &name)
{
    d->m_defaultButtonText[wizardButton] = name;
    this->setButtonText(static_cast<QWizard::WizardButton>(wizardButton), tr(name.toLatin1()));
}*/

// -- PackageManagerPage

/*!
    \class QInstaller::PackageManagerPage
    \inmodule QtInstallerFramework
    \brief The PackageManagerPage class displays information about the product
    to install.
*/

/*!
    \fn PackageManagerPage::~PackageManagerPage()

    Destructs a package manager page.
*/

/*!
    \fn PackageManagerPage::gui() const

    Returns the wizard this page belongs to.
*/

/*!
    \fn PackageManagerPage::isInterruptible() const

    Returns \c true if the installation can be interrupted.
*/

/*!
    \fn PackageManagerPage::setValidatePageComponent(QInstaller::Component *component)

    Sets \a component as the component that validates the page.
*/

/*!
    \fn PackageManagerPage::settingsButtonRequested() const

    Returns \c true if the page requests the wizard to show the \uicontrol Settings button.
*/

/*!
    \fn PackageManagerPage::setSettingsButtonRequested(bool request)

    Determines that the page should request the \uicontrol Settings button if \a request is \c true.
*/

/*!
    \fn PackageManagerPage::entered()

    This signal is called when a page is entered.
*/

/*!
    \fn PackageManagerPage::left()

    This signal is called when a page is left.
*/

/*!
    \fn PackageManagerPage::entering()

    Called when end users enter the page and the PackageManagerGui:currentPageChanged()
    signal is triggered. Supports the QWizardPage::​initializePage() function to ensure
    that the page's fields are properly initialized based on fields from previous pages.
    Otherwise, \c initializePage() would only be called once if the installer has been
    set to QWizard::IndependentPages.
*/

/*!
    \fn PackageManagerPage::leaving()

    Called when end users leave the page and the PackageManagerGui:currentPageChanged()
    signal is triggered.
*/

/*!
    Constructs a package manager page with \a core as parent.
*/
PackageManagerPageObj::PackageManagerPageObj(PackageManagerObj *obj)
    : QObject(obj)
	, m_complete(true)
    , m_needsSettingsButton(false)
	, m_gui(obj)
    , m_core(obj->core())
    , validatorComponent(0)
{
    
}

void PackageManagerPageObj::objInitColor(QWidget* widget)
{
	if (!m_core->settings().titleColor().isEmpty()) {
		m_titleColor = m_core->settings().titleColor();
	}
	else {
		QColor defaultColor = widget->style()->standardPalette().text().color();
		m_titleColor = defaultColor.name();
	}

	//setPixmap(QWizard::WatermarkPixmap, watermarkPixmap());
	//setPixmap(QWizard::BannerPixmap, bannerPixmap());
	//setPixmap(QWizard::LogoPixmap, logoPixmap());
}

void PackageManagerPageObj::setErrorMessage(const QString &error) 
{
	emit m_core->metaJobInfoMessage(error);
}

/*!
    Returns the package manager core.
*/
PackageManagerCore *PackageManagerPageObj::packageManagerCore() const
{
    return m_core;
}

/*!
    Returns the watermark pixmap specified in the \c <Watermark> element of the package information
    file.
*/
QPixmap PackageManagerPageObj::watermarkPixmap() const
{
    return QPixmap(m_core->value(QLatin1String("WatermarkPixmap")));
}

/*!
    Returns the banner pixmap specified in the \c <Banner> element of the package information file.
    Only used by the modern UI style.
*/
QPixmap PackageManagerPageObj::bannerPixmap(QWidget* widget) const
{
    QPixmap banner(m_core->value(QLatin1String("BannerPixmap")));

    if (!banner.isNull()) {
        int width;
        if (m_core->settings().containsValue(QLatin1String("WizardDefaultWidth")) )
            width = m_core->settings().wizardDefaultWidth();
        else
            width = widget->size().width();
        banner = banner.scaledToWidth(width, Qt::SmoothTransformation);
    }
    return banner;
}

/*!
    Returns the logo pixmap specified in the \c <Logo> element of the package information file.
*/
QPixmap PackageManagerPageObj::logoPixmap() const
{
    return QPixmap(m_core->value(QLatin1String("LogoPixmap")));
}

/*!
    Returns the product name of the application being installed.
*/
QString PackageManagerPageObj::productName() const
{
    return m_core->value(QLatin1String("ProductName"));
}

/*!
    Sets the font color of \a title. The title is specified in the \c <Title>
    element of the package information file. It is the name of the installer as
    displayed on the title bar.
*/
void PackageManagerPageObj::setColoredTitle(const QString &title, QWizardPage* widget)
{
	widget->setTitle(QString::fromLatin1("<font color=\"%1\">%2</font>").arg(m_titleColor, title));
}

/*!
    Sets the font color of \a subTitle.
*/
void PackageManagerPageObj::setColoredSubTitle(const QString &subTitle, QWizardPage* widget)
{
	widget->setSubTitle(QString::fromLatin1("<font color=\"%1\">%2</font>").arg(m_titleColor, subTitle));
}

/*!
    Returns \c true if the page is complete; otherwise, returns \c false.
*/
bool PackageManagerPageObj::isComplete() const
{
    return m_complete;
}

/*!
    Sets the package manager page to complete if \a complete is \c true. Emits
    the completeChanged() signal.
*/
void PackageManagerPageObj::setComplete(bool complete)
{
    m_complete = complete;
    /*if (QWizard *w = widget->wizard()) {
        if (QAbstractButton *cancel = w->button(QWizard::CancelButton)) {
            if (cancel->hasFocus()) {
                if (QAbstractButton *next = w->button(QWizard::NextButton))
                    next->setFocus();
            }
        }
    }*/
    emit completeChanged();
}

/*!
    Sets the \a component that validates the page.
*/
void PackageManagerPageObj::setValidatePageComponent(Component *component)
{
    validatorComponent = component;
}

/*!
    Returns \c true if the end user has entered complete and valid information.
*/
bool PackageManagerPageObj::validatePage()
{
    if (validatorComponent)
        return validatorComponent->validatePage();
    return true;
}

/*!
    Inserts \a widget at the position specified by \a offset in relation to
    another widget specified by \a siblingName. The default position is directly
    behind the sibling.
*/
void PackageManagerPageObj::insertWidget(QWidget *widget, const QString &siblingName, int offset)
{
    QWidget *sibling = findChild<QWidget *>(siblingName);
    QWidget *parent = sibling ? sibling->parentWidget() : 0;
    QLayout *layout = parent ? parent->layout() : 0;
    QBoxLayout *blayout = qobject_cast<QBoxLayout *>(layout);

    if (blayout) {
        const int index = blayout->indexOf(sibling) + offset;
        blayout->insertWidget(index, widget);
    }
}

/*!
    Returns the widget specified by \a objectName.
*/
QWidget *PackageManagerPageObj::findWidget(const QString &objectName) const
{
    return findChild<QWidget*> (objectName);
}

/*!
    Determines which page should be shown next depending on whether the
    application is being installed, updated, or uninstalled.

    The license check page is shown only if a component that provides a license
    is selected for installation. It is hidden during uninstallation and update.
*/
int PackageManagerPageObj::nextId() const
{
    const int next = gui()->nextId(); // the page to show next
    if (next == PackageManagerCore::LicenseCheck) {
        // calculate the page after the license page
        const int nextNextId = gui()->pageIds().value(gui()->pageIds().indexOf(next) + 1, -1);
        const PackageManagerCore *const core = packageManagerCore();
        if (core->isUninstaller())
            return nextNextId;  // forcibly hide the license page if we run as uninstaller

        core->calculateComponentsToInstall();
        foreach (Component* component, core->orderedComponentsToInstall()) {
            if (core->isMaintainer() && component->isInstalled())
                continue; // package manager or updater, hide as long as the component is installed

            // The component is about to be installed and provides a license, so the page needs to
            // be shown.
            if (!component->licenses().isEmpty())
                return next;
        }
        return nextNextId;  // no component with a license or all components with license installed
    }
    return next;    // default, show the next page
}

/////////////////////////////////////////////////////////////////////
IntroductionPageObj::IntroductionPageObj(PackageManagerObj *obj)
	: PackageManagerPageObj(obj)
	, m_updatesFetched(false)
	, m_allPackagesFetched(false)
{

}

void IntroductionPageObj::entering()
{
	PackageManagerCore *core = packageManagerCore();

	setComplete(false);
	fetchUpdaterPackages();
	fetchCommonPackages();
	if (core->isUpdater()) {
		core->componentsToInstallNeedsRecalculation();
	}

	if (core->isUpdater() && core->components(QInstaller::PackageManagerCore::ComponentType::Root).count() <= 0)
	{
		core->updateFinished();
		return;
	}
	gui()->nextPage();
}

bool IntroductionPageObj::validRepositoriesAvailable() const
{
	const PackageManagerCore *const core = packageManagerCore();
	bool valid = (core->isInstaller() && core->isOfflineOnly()) || core->isUninstaller();

	if (!valid) {
		foreach(const Repository &repo, core->settings().repositories()) {
			if (repo.isEnabled() && repo.isValid()) {
				valid = true;
				break;
			}
		}
	}
	return valid;
}

bool IntroductionPageObj::fetchUpdaterPackages()
{
	PackageManagerCore *core = packageManagerCore();
	setComplete(false);

	// fetch updater packages
	if (core->isUpdater()) {
		if (!m_updatesFetched) {
			m_updatesFetched = core->fetchRemotePackagesTree();
			if (!m_updatesFetched)
				setErrorMessage(core->error());
		}

		if (m_updatesFetched) {
			if (core->components(QInstaller::PackageManagerCore::ComponentType::Root).count() <= 0)
				setErrorMessage(QString::fromLatin1("<b>%1</b>").arg(tr("No updates available.")));
			else
				setComplete(true);
		}
	}

	return isComplete();
}

bool IntroductionPageObj::fetchCommonPackages()
{
	PackageManagerCore *core = packageManagerCore();
	setComplete(false);

	// fetch common packages
	if (core->isInstaller() || core->isPackageManager()) {
		bool localPackagesTreeFetched = false;
		if (!m_allPackagesFetched) {
			// first try to fetch the server side packages tree
			m_allPackagesFetched = core->fetchRemotePackagesTree();
			if (!m_allPackagesFetched) {
				QString error = core->error();
				if (core->isPackageManager() && core->status() != PackageManagerCore::ForceUpdate) {
					// if that fails and we're in maintenance mode, try to fetch local installed tree
					localPackagesTreeFetched = core->fetchLocalPackagesTree();
					if (localPackagesTreeFetched) {
						// if that succeeded, adjust error message
						error = QLatin1String("<font color=\"red\">") + error + tr(" Only local package "
							"management available.") + QLatin1String("</font>");
					}
				}
				setErrorMessage(error);
			}
		}

		if (m_allPackagesFetched || localPackagesTreeFetched)
			setComplete(true);
	}

	return isComplete();
}

/////////////////////////////////////////////////////////////////////
PerformInstallationPageObj::PerformInstallationPageObj(PackageManagerObj *obj)
	: PackageManagerPageObj(obj)
	, m_iLastProgress(0)
{
	m_updateTimer = new QTimer(this);

	connect(m_updateTimer, &QTimer::timeout,
		this, &PerformInstallationPageObj::updateProgress); //updateProgress includes label

	m_updateTimer->setInterval(30);
}

void PerformInstallationPageObj::entering()
{
	PackageManagerCore *core = packageManagerCore();
	emit core->metaJobTotalProgress(100);
	m_iLastProgress = 0;

	m_updateTimer->start();
	setComplete(false);

	if (packageManagerCore()->isUninstaller()) {
		QTimer::singleShot(30, packageManagerCore(), SLOT(runUninstaller()));
	}
	else if (packageManagerCore()->isMaintainer()) {
		QTimer::singleShot(30, packageManagerCore(), SLOT(runPackageUpdater()));
	}
	else {
		QTimer::singleShot(30, packageManagerCore(), SLOT(runInstaller()));
	}

}

void PerformInstallationPageObj::updateProgress()
{
	QInstaller::ProgressCoordinator *progressCoordninator = QInstaller::ProgressCoordinator::instance();
	const int progressPercentage = progressCoordninator->progressInPercentage();

	PackageManagerCore *core = packageManagerCore();

	if (m_iLastProgress == progressPercentage) return;
	emit core->metaJobProgress(progressPercentage);
	m_iLastProgress = progressPercentage;

	if (progressPercentage == 100)
	{
		m_updateTimer->stop();
	}
}